package e310

import (
	"encoding/binary"
	"errors"
	"github.com/lishimeng/go-log"
	"time"
)

func (c *Client) packetSplit() {
	log.Info("start connector")
	c.io.Start()
	for {
		select {
		case <-c.ctx.Done():
			return
		default:
			c.packetSplitExec()
		}
	}
}

var tmp = make([]byte, 8)
var packetBufOffset = 0
var hasPacket = false
var head byte
var packetBuf = make([]byte, 1024)

func (c *Client) resetPacketFlag() {
	packetBufOffset = 0
	hasPacket = false // tmp有数据的时候进入找packet头阶段
	head = 0x00
}

func (c *Client) onPacket(packet []byte) {
	//log.Info("on_packet: %02x", packet)
	p := Packet{}
	err := p.Parse(packet)
	if err != nil {
		log.Info("parse packet err")
		log.Info(err)
		return
	}
	switch p.Type {
	case PacketTypeNotify:
		c.onNotifyPacket(p)
	case PacketTypeResp:
		c.onRespPacket(p)
	}
}

func (c *Client) onRespPacket(packet Packet) {

	//log.Info("on_resp_packet")
	c.respChan <- 0x00
	if c.respListener != nil {
		c.respListener(packet)
	}
}

func (c *Client) onNotifyPacket(packet Packet) {
	//log.Info("on_notify_packet")
	c.notifyChan <- 0x00
	if c.notifyListener == nil {
		return
	}
	c.notifyListener(packet)
}

var TimeoutErr = errors.New("timeout")

func (c *Client) wait() (err error) {
	timeout := time.NewTimer(time.Second)
	defer timeout.Stop()
	func() {
		select {
		case <-c.ctx.Done():
			return
		case <-c.respChan:
			//log.Info("<<-resp packet")
			return
		case <-c.notifyChan:
			//log.Info("<<-notify packet")
			timeout.Reset(time.Millisecond * 20 * 50) // 等待下一个notify
		case <-timeout.C:
			//log.Info("reader rx stream timeout")
			if c.timeoutListener != nil {
				c.timeoutListener()
			}
			err = TimeoutErr
		}
	}()
	return
}

func (c *Client) packetSplitExec() {

	var dataLen = c.io.BufLen()
	if dataLen == 0 {
		return
	}

	n, err := c.io.Read(tmp) // 读一段
	if err != nil {
		return
	}
	if n == 0 {
		return
	}
	if packetBufOffset > 0 {
		hasPacket = true
	}

	for i := 0; i < n; i++ { // 从1号坐标开始
		if !hasPacket {
			head = tmp[i]
			if head == 0xBB { // 找到packet头
				packetBuf[0] = head
				packetBufOffset = packetBufOffset + 1
				hasPacket = true // 标记为packet
				continue
			}
		} else {
			// Header | Frame type | Command | Param Length | Param | Checksum | Tail
			// 0        1            2         3 4            5       6          7
			if !(packetBuf[0] == 0xBB) {
				log.Info("error packet")
				c.resetPacketFlag()
			}
			if packetBufOffset < 7 { // 基本包厂, 不包括parameter字段
				packetBuf[packetBufOffset] = tmp[i]
				packetBufOffset++
			} else {
				var payloadLen16 = binary.BigEndian.Uint16(packetBuf[3:5])
				var payloadLen = int(payloadLen16)
				if payloadLen > 32 {
					c.resetPacketFlag()
					continue
				}
				if packetBufOffset < (payloadLen + 7) { // 接收param部分
					packetBuf[packetBufOffset] = tmp[i]
					packetBufOffset++
				}
				if packetBufOffset == (payloadLen + 7) { // 将上面拆分出的packet复制出来
					var packet = make([]byte, payloadLen+7) // 复制出完整包
					copyBuf(packetBuf, 0, packet, 0, payloadLen+7)
					// TODO check packet_tail
					c.resetPacketFlag()
					go func() {
						c.onPacket(packet)
					}()
				}
			}
		}
	}
}
